// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie.network.packets.hit;

import java.nio.ByteBuffer;
import java.util.ArrayList;
import zombie.characters.IsoGameCharacter;
import zombie.characters.IsoPlayer;
import zombie.characters.SurvivorDesc;
import zombie.characters.skills.PerkFactory;
import zombie.core.network.ByteBufferWriter;
import zombie.core.raknet.UdpConnection;
import zombie.inventory.types.HandWeapon;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.network.ServerOptions;
import zombie.network.packets.INetworkPacket;

public class Player extends Character implements INetworkPacket {
    protected IsoPlayer player;
    protected short playerIndex;
    protected short playerFlags;
    protected float charge;
    protected float perkAiming;
    protected float combatSpeed;
    protected String attackType;
    protected AttackVars attackVars = new AttackVars();
    ArrayList<HitInfo> hitList = new ArrayList();

    public void set(IsoPlayer _player, boolean isCriticalHit) {
        super.set(_player);
        this.playerIndex = _player.isLocal() ? (short)_player.getPlayerNum() : -1;
        this.player = _player;
        this.playerFlags = 0;
        this.playerFlags = (short)(this.playerFlags | (short)(_player.isAimAtFloor() ? 1 : 0));
        this.playerFlags = (short)(this.playerFlags | (short)(_player.isDoShove() ? 2 : 0));
        this.playerFlags = (short)(this.playerFlags | (short)(_player.isAttackFromBehind() ? 4 : 0));
        this.playerFlags |= (short)(isCriticalHit ? 8 : 0);
        this.charge = _player.useChargeDelta;
        this.perkAiming = (float)_player.getPerkLevel(PerkFactory.Perks.Aiming);
        this.combatSpeed = _player.getVariableFloat("CombatSpeed", 1.0F);
        this.attackType = _player.getAttackType();
        this.attackVars.copy(_player.attackVars);
        this.hitList.clear();
        this.hitList.addAll(_player.hitList);
    }

    public void parsePlayer(UdpConnection connection) {
        if (GameServer.bServer) {
            if (connection != null && this.playerIndex != -1) {
                this.player = GameServer.getPlayerFromConnection(connection, this.playerIndex);
            } else {
                this.player = (IsoPlayer)GameServer.IDToPlayerMap.get(this.ID);
            }

            this.character = this.player;
        } else if (GameClient.bClient) {
            this.player = (IsoPlayer)GameClient.IDToPlayerMap.get(this.ID);
            if (this.player == null) {
                IsoPlayer isoPlayer = IsoPlayer.getInstance();
                if (isoPlayer != null) {
                    this.player = new IsoPlayer(isoPlayer.getCell(), new SurvivorDesc(), (int)isoPlayer.x, (int)isoPlayer.y, (int)isoPlayer.z);
                }
            }

            this.character = this.player;
        }
    }

    @Override
    public void parse(ByteBuffer b, UdpConnection connection) {
        super.parse(b, connection);
        this.playerIndex = b.getShort();
        this.playerFlags = b.getShort();
        this.charge = b.getFloat();
        this.perkAiming = b.getFloat();
        this.combatSpeed = b.getFloat();
        this.attackType = zombie.GameWindow.ReadString(b);
        this.attackVars.parse(b, connection);
        byte _byte = b.get();

        for (int _int = 0; _int < _byte; _int++) {
            HitInfo hitInfo = new HitInfo();
            hitInfo.parse(b, connection);
            this.hitList.add(hitInfo);
        }
    }

    @Override
    public void write(ByteBufferWriter b) {
        super.write(b);
        b.putShort(this.playerIndex);
        b.putShort(this.playerFlags);
        b.putFloat(this.charge);
        b.putFloat(this.perkAiming);
        b.putFloat(this.combatSpeed);
        b.putUTF(this.attackType);
        this.attackVars.write(b);
        byte _byte = (byte)this.hitList.size();
        b.putByte(_byte);

        for (int _int = 0; _int < _byte; _int++) {
            ((HitInfo)this.hitList.get(_int)).write(b);
        }
    }

    @Override
    public boolean isConsistent() {
        return super.isConsistent() && this.player != null;
    }

    @Override
    public String getDescription() {
        String string = "";
        byte _byte = (byte)Math.min(100, this.hitList.size());

        for (int _int = 0; _int < _byte; _int++) {
            HitInfo hitInfo = (HitInfo)this.hitList.get(_int);
            string = string + hitInfo.getDescription();
        }

        return super.getDescription()
            + "\n\tPlayer [ player "
            + (this.player == null ? "?" : "\"" + this.player.getUsername() + "\"")
            + " | charge="
            + this.charge
            + " | perkAiming="
            + this.perkAiming
            + " | combatSpeed="
            + this.combatSpeed
            + " | attackType=\""
            + this.attackType
            + "\" | isAimAtFloor="
            + ((this.playerFlags & 1) != 0)
            + " | isDoShove="
            + ((this.playerFlags & 2) != 0)
            + " | isAttackFromBehind="
            + ((this.playerFlags & 4) != 0)
            + " | isCriticalHit="
            + ((this.playerFlags & 8) != 0)
            + " | _bodyDamage="
            + (this.player == null ? "?" : this.player.getBodyDamage().getHealth())
            + this.attackVars.getDescription()
            + "\n\t hitList=["
            + string
            + "](count="
            + this.hitList.size()
            + ") ]";
    }

    @Override
    void process() {
        super.process();
        this.player.useChargeDelta = this.charge;
        this.player.setVariable("recoilVarX", this.perkAiming / 10.0F);
        this.player.setAttackType(this.attackType);
        this.player.setVariable("CombatSpeed", this.combatSpeed);
        this.player.setVariable("AimFloorAnim", (this.playerFlags & 1) != 0);
        this.player.setAimAtFloor((this.playerFlags & 1) != 0);
        this.player.setDoShove((this.playerFlags & 2) != 0);
        this.player.setAttackFromBehind((this.playerFlags & 4) != 0);
        this.player.setCriticalHit((this.playerFlags & 8) != 0);
    }

    void attack(HandWeapon handWeapon, boolean _boolean) {
        if (GameClient.bClient) {
            this.player.attackStarted = false;
            this.player.attackVars.copy(this.attackVars);
            this.player.hitList.clear();
            this.player.hitList.addAll(this.hitList);
            this.player.pressedAttack(false);
            if (this.player.isAttackStarted() && handWeapon.isRanged() && !this.player.isDoShove()) {
                this.player.startMuzzleFlash();
            }

            if (handWeapon.getPhysicsObject() != null) {
                this.player.Throw(handWeapon);
            }
        } else if (GameServer.bServer && _boolean && !this.player.getSafety().isEnabled()) {
            this.player.getSafety().setCooldown(this.player.getSafety().getCooldown() + (float)ServerOptions.getInstance().SafetyCooldownTimer.getValue());
            GameServer.sendChangeSafety(this.player.getSafety());
        }
    }

    @Override
    public IsoGameCharacter getCharacter() {
        return this.player;
    }

    public IsoPlayer getPlayer() {
        return this.player;
    }

    boolean isRelevant(UdpConnection udpConnection) {
        return udpConnection.RelevantTo(this.positionX, this.positionY);
    }
}
